﻿
namespace Huirui.Cavan.Presentation.Seedwork
{
    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Diagnostics.Contracts;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Web.Configuration;
    using System.Web.Mvc;
    using System.Web.Routing;
    using Huirui.Cavan.Core.Extension;
    using System.Web;
    using Huirui.Cavan.Core.Message;

    public abstract class WebController<TModel> : Controller, IWebController<TModel>
        where TModel : class, IWebModel
    {
        #region members
        TModel _model;
        AopUrlHelper _aopUrlHelper;
        #endregion members

        #region init
        protected override void Initialize(RequestContext requestContext)
        {
            base.Initialize(requestContext);
            Model.MasterModel.ControllerName = ControllerName;
        }
        #endregion init

        #region properties
        public abstract string ControllerName { get; }

        public virtual TModel Model
        {
            get
            {

                _model.Messages = _model.Messages ?? new List<AppMessage>();
                return _model;
            }
            set { _model = value; }
        }

        public abstract bool UseDenied { get; }

        public new virtual IUrlHelper Url
        {
            get
            {
                if (_aopUrlHelper.IsNull())
                {
                    _aopUrlHelper = new AopUrlHelper(base.Url.RequestContext, base.Url.RouteCollection);
                }
                return _aopUrlHelper;
            }
        }
        #endregion

        #region IObjectBinder
        public virtual bool BindModel<T>(T model)
            where T : class
        {
            return BindModel(model, null);
        }

        public virtual bool BindModel<T>(T model, string prefix = null, string[] includeProperties = null, string[] excludeProperties = null, IValueProvider valueProvider = null)
            where T : class
        {
            Contract.Requires(model.Is(), "Cannot bind null object from Form data");
            try
            {
                if (!TryUpdateModel(model, prefix, includeProperties, excludeProperties, valueProvider ?? ValueProvider))
                {
                    foreach (var message in ModelState.Where(pair => pair.Value.Errors.Count > 0))
                    {
                        var val = message.Value.Value.Is()
                                      ? message.Value.Value.AttemptedValue
                                      : message.Value.Errors[0].ErrorMessage.Is()
                                            ? message.Value.Errors[0].ErrorMessage
                                            : message.Value.Errors[0].Exception.Message;
                        Model.Messages.AddError(this,"BindingError"
                            , "BindingError:{0}{1}{2}"
                            , message.Key
                            , ControllerName
                            , val);
                    }
                }
                return ModelState.IsValid;
            }
            catch (Exception ex)
            {
                Model.Messages.AddException(this, "Exception", ex);
            }
            return false;
        }
        #endregion

        #region override HandleUnknownAction
        protected override void HandleUnknownAction(string actionName)
        {
            this.Log().Debug("User {0} tried to access unknown action '{1}' on controller '{2}' "
                .FormatWith(User.Identity.Name, actionName, Model.MasterModel.ControllerName));      
        }
        #endregion override HandleUnknownAction
    }
}